#!/usr/bin/python3
# -*- coding: utf-8 -*-
# coding=utf-8
# Author: BillySir
from __future__ import print_function
import sys
from rule import *
from chess_board import *
from dimension import T2D

print_process = False  # 是否打印解题（试填）过程
width = 6  # 每行多少格


class FleetCell(Cell):
    """海面方块"""

    def __init__(self, basket: ChessBasket):
        super(FleetCell, self).__init__(basket)

    def validate(self) -> bool:
        from dimension import T2D
        if self.index in (0, 5, 20) and self.chess.name != 0:
            return False
        if self.index == 31 and self.chess.name != 2:
            return False
        if self.chess is None:
            return True
        # 1的邻8（邻接8格）须是0
        if self.chess.name == 1:
            if len([near for near in T2D.near8(self) if near.chess is not None and near.chess.name != 0]) > 0:
                return False
        # 2的邻4须是2或3，而且只能一个方向有
        if self.chess.name == 2:
            # 邻4角须是0
            if len([near for near in T2D.near4corner(self) if near.chess is not None and near.chess.name != 0]) > 0:
                return False
            # 邻4须是2或3
            if len([near for near in T2D.near4(self) if
                    near.chess is not None and near.chess.name not in (0, 2, 3)]) > 0:
                return False
            # 邻4的2或3最多1个
            if len([near for near in T2D.near4(self) if near.chess is not None and near.chess.name in (2, 3)]) > 1:
                return False
        # 3的邻接4必须是2，而且在两头，其它6格必须是0
        if self.chess.name == 3:
            # 邻8须是0或2
            if len([near for near in T2D.near8(self) if near.chess is not None and near.chess.name not in (0, 2)]) > 0:
                return False
            # 邻4角须是0
            if len([near for near in T2D.near4corner(self) if near.chess is not None and near.chess.name != 0]) > 0:
                return False
            # 不允许横竖都有2
            count_ew2 = len([near for near in T2D.ew(self) if near.chess is not None and near.chess.name == 2])
            count_sn2 = len([near for near in T2D.sn(self) if near.chess is not None and near.chess.name == 2])
            if count_ew2 > 0 and count_sn2 > 0:
                return False
            # 不允许横竖都有0
            count_ew0 = len([near for near in T2D.ew(self) if near.chess is not None and near.chess.name == 0])
            count_sn0 = len([near for near in T2D.sn(self) if near.chess is not None and near.chess.name == 0])
            if count_ew0 > 0 and count_sn0 > 0:
                return False
        return True


def run():
    """舰队谜题"""

    # 初始化棋子(船只)
    chess0 = Chess(0, 0)  # 没有船只
    chess1 = Chess(1, 1)  # 1段般只，即救生艇
    chess2 = Chess(2, 1)  # 2段、3段船只的头段和尾段
    chess3 = Chess(3, 1)  # 3段船只的中间段
    chess_list = [chess0, chess1, chess2, chess3]
    # 初始化棋盒
    chess_dist = {chess0: 26, chess1: 3, chess2: 6, chess3: 1}
    # print('chess_dist:' + str(chess_dist))
    basket = ChessBasket(chess_dist)

    # 初始化棋盘上的格子
    cells = [FleetCell(basket) for _ in range(36)]
    # 初始化棋盘
    board = ChessBoard(cells)
    board.print_process = print_process
    board.width = width

    # 初始化二维变换
    T2D.board = board
    T2D.width = width
    T2D.height = width
    outside_cell = Cell(None)
    outside_cell.set_chess(chess0)
    T2D.outside_cell = outside_cell

    # 初始化规则
    rules = [RuleSum(2, basket), RuleSum(1, basket), RuleSum(1, basket),
             RuleSum(3, basket), RuleSum(1, basket), RuleSum(2, basket),
             RuleSum(3, basket), RuleSum(0, basket), RuleSum(2, basket),
             RuleSum(2, basket), RuleSum(1, basket), RuleSum(2, basket)]
    # 横向验证
    rules[0].bind_parents(cells[0:6])
    rules[1].bind_parents(cells[6:12])
    rules[2].bind_parents(cells[12:18])
    rules[3].bind_parents(cells[18:24])
    rules[4].bind_parents(cells[24:30])
    rules[5].bind_parents(cells[30:36])
    # 纵向验证
    rules[6].bind_parents(cells[5::6])
    rules[7].bind_parents(cells[4::6])
    rules[8].bind_parents(cells[3::6])
    rules[9].bind_parents(cells[2::6])
    rules[10].bind_parents(cells[1::6])
    rules[11].bind_parents(cells[0::6])
    board.rules = rules

    # 向左验证
    T2D.set_child(lambda x, y: (x - 1, y))
    # 向上验证
    T2D.set_child(lambda x, y: (x, y - 1))

    # 放固定棋子
    _ = None
    known = [
        0, _, _, _, _, 0,
        _, _, _, _, _, _,
        _, _, _, _, _, _,
        _, _, 0, _, _, _,
        _, _, _, _, _, _,
        _, 2, _, _, _, _,
    ]
    for i in range(len(known)):
        value = known[i]
        if value is not None:
            chess = basket.get_chess_by_name(value)
            board.put_chess(i, chess[0])

    # 启动求解

    board.guess()
    print("finished")
    print("guess count: %d" % basket.guess_count)
